import _ from 'lodash-es'
import JSZip from 'jszip'
import FileSaver from 'file-saver'
export function isExternal(path: string) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

export function uuid() {
  const s: Array<any> = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = s[13] = s[18] = s[23] = '-'
  const uuid = s.join('')
  return uuid
}

export function randomString(length: number) {
  const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = ''
  for (let i = length; i > 0; --i) {
    result += str[Math.floor(Math.random() * str.length)]
  }
  return result
}

/**
 * 中划线字符驼峰
 * @param {*} str 要转换的字符串
 * @returns 返回值
 */
export function toHump(str: string): string {
  if (!str) return str
  return str
    .replace(/\-(\w)/g, function (all, letter) {
      return letter.toUpperCase()
    })
    .replace(/(\s|^)[a-z]/g, function (char) {
      return char.toUpperCase()
    })
}

export function sortColumns(originColumns: any[], newColumns: any[]) {
  if (!originColumns || !newColumns) {
    return
  }
  if (newColumns.length === 0) {
    originColumns.length = 0
  } else {
    const selectionItem = originColumns.find((it) => it.type === 'selection')
    originColumns.length = 0
    if (selectionItem) {
      originColumns.push(selectionItem)
    }
    originColumns.push(...newColumns)
  }
}

export function getNowDate() {
  const date = new Date()
  const sign2 = ':'
  const year = date.getFullYear() // 年
  let month: string | number = date.getMonth() + 1 // 月
  let day: string | number = date.getDate() // 日
  let hour: string | number = date.getHours() // 时
  let minutes: string | number = date.getMinutes() // 分
  let seconds: string | number = date.getSeconds() //秒
  const weekArr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天']
  const week = weekArr[date.getDay()]
  // 给一位数的数据前面加 “0”
  if (month >= 1 && month <= 9) {
    month = '0' + month
  }
  if (day >= 0 && day <= 9) {
    day = '0' + day
  }
  if (hour >= 0 && hour <= 9) {
    hour = '0' + hour
  }
  if (minutes >= 0 && minutes <= 9) {
    minutes = '0' + minutes
  }
  if (seconds >= 0 && seconds <= 9) {
    seconds = '0' + seconds
  }
  return [year + '-' + month + '-' + day, hour + sign2 + minutes + sign2 + seconds, week]
}
/**
 * @desc 过滤空的key，再http请求之前把不需要的空key过滤掉
 * @param data 需要过滤的数据
 * @param filterData 是否需要过滤  默认true，过滤为空的数据
 * @param isTrim 是否需要删除前后空格
 */
export const filterData = (data: { [propName: string]: any }, filterData = true, isTrim: any) => {
  if (!data || !filterData) return data
  const o: any = {}
  for (const i in data) {
    if (data[i] === null || data[i] === undefined || data[i] === '') continue
    // 需要过滤前后空格，校验是否是String类型（默认用于get查询的时候使用）
    const trimVal = isTrim ? (typeof data[i] === 'string' ? data[i]?.trim() : data[i]) : data[i]
    o[i] = trimVal
  }
  return o
}
/**
 * 统一处理JSON转化，异常情况
 * @param {} val
 * @param {*} defaultObj
 */
export function parseJson(val: any, defaultObj: any) {
  if (!val) return defaultObj || []
  try {
    return JSON.parse(val)
  } catch (e) {
    return defaultObj ? defaultObj : null
  }
}

/**
 * JS使用递归删除children中长度为空的数组
 * @param [] arr 树结构
 */
export function delateMenuChildren(arr: Array<any>, type?: string) {
  const name = type ? type : 'children'
  if (arr.length) {
    for (const i in arr) {
      if (arr[i][name]?.length) {
        delateMenuChildren(arr[i][name], type)
      } else {
        delete arr[i][name]
      }
    }
  }
  return arr
}
export function treeFindPath(tree: any, func: any, path = []): any {
  if (!tree) return []
  for (const data of tree) {
    // 这里按照你的需求来存放最后返回的内容吧
    path.push(data)
    if (func(data)) return path
    if (data.children) {
      const findChildren = treeFindPath(data.children, func, path)
      if (findChildren.length) return findChildren
    }
    path.pop()
  }
  return []
}

export function getArrayByArrays(arrays: any) {
  let arr: any = [''] // 初始化第一个内层数组

  /**
   * 遍历外层数组
   */
  for (let index = 0; index < arrays.length; index++) {
    // console.log('外层数组索引 = ' + index);
    arr = getValuesByArray(arr, arrays[index])
  }
  return arr
}

function getValuesByArray(arr1: any, arr2: any) {
  const arr: any = []

  /**
   * 遍历外层数组
   */
  for (let index = 0; index < arr1.length; index++) {
    const value1 = arr1[index]

    /**
     * 遍历内层数组
     */
    for (let cursor = 0; cursor < arr2.length; cursor++) {
      const value2 = arr2[cursor]
      const value = [...value1, value2]

      arr.push(value)
    }
  }

  return arr
}
/**
 * 查询子节点
 * @param {Array} data  tree数据
 * @param {String} value 当前id值
 * @param {String} key 节点里需要匹配的字段名
 * @param {String} childrenkey 子节点字段名
 */
export function findChildrenArray(data: any, value: any, key = 'dept', childrenKey = 'children') {
  let findedItem = null
  for (let i = 0; i < data.length; i++) {
    if (data[i][key] == value) {
      findedItem = data[i]
      return findedItem
    } else {
      if (data[i]?.[childrenKey]?.length) {
        const result: any = findChildrenArray(data[i][childrenKey], value, key)
        if (result) return result
      }
    }
  }
  return null
}

/**
 * 对比两个数组中的元素是否全等，数组里面的元素不固定
 * field 排序字段，用于排序对象
 */
export const arraysAreEqual = (array1: any, array2: any, field: string) => {
  if (array1.length !== array2.length) {
    return false
  }
  const sortedArray1 = array1.slice().sort((a: any, b: any) => a[field].localeCompare(b[field], 'zh-CN'))
  const sortedArray2 = array2.slice().sort((a: any, b: any) => a[field].localeCompare(b[field], 'zh-CN'))

  for (let i = 0; i < sortedArray1.length; i++) {
    if (sortedArray1[i][field] != sortedArray2[i][field]) {
      return false
    }
  }
  return true
}

// 图片添加水印
export const addwatermark = (file: any) => {
  return new Promise((resolve) => {
    const reader = new FileReader()
    reader.readAsDataURL(file) // file转base64
    reader.onload = (e: any) => {
      const canvas = document.createElement('canvas')
      const img: any = new Image()
      img.src = e.target.result
      img.onload = () => {
        const ctx: any = canvas.getContext('2d')
        let data = ''
        const imgWidth = img.width
        const imgHeight = img.height
        const fontsize = imgWidth > imgHeight ? imgHeight / 10 : imgWidth / 10 // 设定文字大小随图片大小变化
        canvas.width = imgWidth // 画布宽度
        canvas.height = imgHeight // 画布高度
        ctx.drawImage(img, 0, 0, imgWidth, imgHeight) // 绘制图片大小和先前图片一致
        for (let i = 1; i <= 20; i++) {
          ctx.save()
          ctx.translate(i + 50, i + 50)
          ctx.rotate((45 * Math.PI) / 180)
          ctx.fillStyle = 'rgb(0,0,0,0.3)' // 水印颜色，透明度
          ctx.textBaseline = 'center' // 水印对其的基准线
          ctx.font = `50px Verdana` // 文字大小
          ctx.fillText('样品', imgWidth / 2 - i * 200, imgHeight / 2 - i * 200) // 添加的文字
          ctx.restore()

          ctx.save()
          ctx.translate(i + 600, i + 600)
          ctx.rotate((45 * Math.PI) / 180)
          ctx.fillStyle = 'rgb(0,0,0,0.4)' // 水印颜色，透明度
          ctx.textBaseline = 'center' // 水印对其的基准线
          ctx.font = `50px Verdana` // 文字大小
          ctx.fillText('样品', imgWidth / 2 - i * 200, imgHeight / 2 - i * 200) // 添加的文字
          ctx.restore()

          ctx.save()
          ctx.translate(i + 900, i + 900)
          ctx.rotate((45 * Math.PI) / 180)
          ctx.fillStyle = 'rgb(0,0,0,0.4)' // 水印颜色，透明度
          ctx.textBaseline = 'center' // 水印对其的基准线
          ctx.font = `50px Verdana` // 文字大小
          ctx.fillText('样品', imgWidth / 2 - i * 200, imgHeight / 2 - i * 200) // 添加的文字
          ctx.restore()

          ctx.save()
          ctx.translate(i + 1200, i + 1200)
          ctx.rotate((45 * Math.PI) / 180)
          ctx.fillStyle = 'rgb(0,0,0,0.4)' // 水印颜色，透明度
          ctx.textBaseline = 'center' // 水印对其的基准线
          ctx.font = `50px Verdana` // 文字大小
          ctx.fillText('样品', imgWidth / 2 - i * 200, imgHeight / 2 - i * 200) // 添加的文字
          ctx.restore()
          ctx.save()
          ctx.translate(i + 1500, i + 1500)
          ctx.rotate((45 * Math.PI) / 180)
          ctx.fillStyle = 'rgb(0,0,0,0.4)' // 水印颜色，透明度
          ctx.textBaseline = 'center' // 水印对其的基准线
          ctx.font = `50px Verdana` // 文字大小
          ctx.fillText('样品', imgWidth / 2 - i * 200, imgHeight / 2 - i * 200) // 添加的文字
          ctx.restore()
          ctx.save()
          ctx.translate(i + 1800, i + 1800)
          ctx.rotate((45 * Math.PI) / 180)
          ctx.fillStyle = 'rgb(0,0,0,0.4)' // 水印颜色，透明度
          ctx.textBaseline = 'center' // 水印对其的基准线
          ctx.font = `50px Verdana` // 文字大小
          ctx.fillText('样品', imgWidth / 2 - i * 200, imgHeight / 2 - i * 200) // 添加的文字
          ctx.restore()
        }
        data = canvas.toDataURL(file.type) // 输出压缩后的base64
        // base64转file
        const arr: any = data.split(',')
        const mime = arr[0].match(/:(.*?);/)[1]
        const bstr = atob(arr[1])
        let n = bstr.length
        const u8arr = new Uint8Array(n)
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n)
        }
        const files: any = new File([new Blob([u8arr], { type: mime })], file.name, { type: file.type })
        files.uid = file.uid
        resolve(files)
      }
    }
  })
}

export const transNumberToShort = (value: any, decimal = 2) => {
  const k = 10000
  const sizes = ['', '万', '亿', '万亿']
  let i = undefined
  let str = ''
  if (value < k) {
    str = value
  } else {
    i = Math.floor(Math.log(value) / Math.log(k))
    str = (value / Math.pow(k, i)).toFixed(decimal) + sizes[i]
  }
  return str
}

export const downloadMul = (fileList: any, blogTitle: string) => {
  const zip: any = new JSZip()
  const promises = []
  const cache = {}
  for (const item of fileList) {
    // item.feilePath为文件链接地址
    // item.fileName为文件名称
    if (item.url) {
      const promise = getImgArrayBuffer(`${item.url}?response-content-type=application/octet-stream`).then((fileData) => {
        // 下载文件, 并存成ArrayBuffer对象(blob)
        const fileName = item.url.split('/')[item.url.split('/').length - 1]
        zip.file(fileName, fileData, { binary: true }) // 逐个添加文件
        cache[item.fileName] = fileData
      })
      promises.push(promise)
    } else {
      // feilePath地址不存在时提示
      alert(`附件${item.fileName}地址错误，下载失败`)
    }
  }
  Promise.all(promises)
    .then(() => {
      zip.generateAsync({ type: 'blob' }).then((content: any) => {
        // 生成二进制流
        FileSaver.saveAs(content, blogTitle) // 利用file-saver保存文件  blogTitle:自定义文件名
      })
    })
    .catch((res) => {
      alert('文件压缩失败')
    })
}

const getImgArrayBuffer = (url: string) => {
  return new Promise((resolve, reject) => {
    //通过请求获取文件blob格式
    const xmlhttp = new XMLHttpRequest()
    let newUrl = url

    if (newUrl.startsWith('http://')) {
      // 替换协议为HTTPS
      newUrl = newUrl.replace('http://', 'https://')
    }

    xmlhttp.open('GET', newUrl, true)
    xmlhttp.responseType = 'blob'
    xmlhttp.onload = function () {
      if (xmlhttp.status == 200) {
        resolve(xmlhttp.response)
      } else {
        reject(xmlhttp.response)
      }
    }
    xmlhttp.send()
  })
}

export const getImageSize = (file: File) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = function (event: any) {
      const img = new Image()
      img.onload = function () {
        resolve({
          width: img.width,
          height: img.height,
          name: file.name,
        })
      }
      img.src = event.target.result
    }
    reader.onerror = function () {
      reject(new Error('Failed to read file'))
    }
    reader.readAsDataURL(file)
  })
}

export const getImageSizeMul = (fileList: any) => {
  const promiseList: any = []
  for (let index = 0; index < fileList.length; index++) {
    ;((i) => {
      promiseList.push(getImageSize(fileList[i]))
    })(index)
  }
  return Promise.all(promiseList)
}

export const getDataType = (value: any) => {
  const typeStr = Object.prototype.toString.call(value).slice(8, -1)

  // 处理特殊情况
  if (typeStr === 'Object' && value === null) return 'Null'
  if (typeStr === 'Object' && typeof value !== 'object') return `${typeof value} (${typeStr.toLowerCase()})` // 对于boxed primitive objects

  // 返回常见的内置对象类型名称
  switch (typeStr) {
    case 'Array':
      return 'Array'
    case 'Boolean':
    case 'Number':
    case 'String':
      return typeStr.toLowerCase() // 包装对象与原始类型一致显示
    case 'Function':
      return 'Function'
    case 'Date':
      return 'Date'
    case 'RegExp':
      return 'RegExp'
    case 'Error':
      return 'Error' // 还包括其子类如TypeError, ReferenceError等
    case 'Map':
    case 'Set':
    case 'WeakMap':
    case 'WeakSet':
      return typeStr
    case 'Promise':
      return 'Promise'
    case 'Uint8Array':
    case 'Int8Array':
    case 'Uint16Array':
    case 'Int16Array':
    case 'Uint32Array':
    case 'Int32Array':
    case 'Float32Array':
    case 'Float64Array':
    case 'BigInt64Array':
    case 'BigUint64Array':
    case 'Uint8ClampedArray':
      return 'TypedArray'
    default:
      return typeStr.toLowerCase()
  }
}

export const getImgForHttp = (url: string) => {
  return `https://erpapi.selleroa.com/v1/aliyun/oss/getAmazonImage?url=${url}`
}
/**
 * 统一处理任意类型的值转成字符串显示
 * @param {} val
 */
export function getStrVal(val: any) {
  if (!val) return ''
  let value = ''
  if (val instanceof Array) {
    const valFilter = val.filter((str: string) => str)
    value = valFilter.length ? val.join(',') : ''
  } else if (val === 'true' || val === true) {
    value = '是'
  } else if (val === 'false' || val === false) {
    value = '否'
  } else {
    value = val
  }
  return value
}
